package com.insight.repository;

import com.insight.entity.DataSource;
import com.insight.entity.MetadataTable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

/**
 * T046: MetadataTable Repository接口
 * 表元数据数据访问层,使用Spring Data JPA
 *
 * @author Insight Team
 */
@Repository
public interface MetadataTableRepository extends JpaRepository<MetadataTable, Long> {

    /**
     * 根据数据源查找所有表元数据
     *
     * @param dataSource 数据源
     * @return 表元数据列表
     */
    List<MetadataTable> findByDataSource(DataSource dataSource);

    /**
     * 根据数据源ID查找所有表元数据
     *
     * @param dataSourceId 数据源ID
     * @return 表元数据列表
     */
    @Query("SELECT mt FROM MetadataTable mt WHERE mt.dataSource.id = :dataSourceId")
    List<MetadataTable> findByDataSourceId(@Param("dataSourceId") Long dataSourceId);

    /**
     * 根据数据源和schema查找表元数据
     *
     * @param dataSource  数据源
     * @param tableSchema 表模式
     * @return 表元数据列表
     */
    List<MetadataTable> findByDataSourceAndTableSchema(DataSource dataSource, String tableSchema);

    /**
     * 根据数据源、schema和表名查找表元数据
     *
     * @param dataSource  数据源
     * @param tableSchema 表模式
     * @param tableName   表名
     * @return 表元数据Optional
     */
    Optional<MetadataTable> findByDataSourceAndTableSchemaAndTableName(
            DataSource dataSource, String tableSchema, String tableName);

    /**
     * 根据数据源ID、schema和表名查找表元数据
     *
     * @param dataSourceId 数据源ID
     * @param tableSchema  表模式
     * @param tableName    表名
     * @return 表元数据Optional
     */
    @Query("SELECT mt FROM MetadataTable mt WHERE mt.dataSource.id = :dataSourceId " +
            "AND mt.tableSchema = :tableSchema AND mt.tableName = :tableName")
    Optional<MetadataTable> findByDataSourceIdAndTableSchemaAndTableName(
            @Param("dataSourceId") Long dataSourceId,
            @Param("tableSchema") String tableSchema,
            @Param("tableName") String tableName);

    /**
     * 根据表类型查找表元数据
     *
     * @param tableType 表类型
     * @return 表元数据列表
     */
    List<MetadataTable> findByTableType(String tableType);

    /**
     * 根据数据源和表类型查找表元数据
     *
     * @param dataSource 数据源
     * @param tableType  表类型
     * @return 表元数据列表
     */
    List<MetadataTable> findByDataSourceAndTableType(DataSource dataSource, String tableType);

    /**
     * 分页查询指定数据源的表元数据
     *
     * @param dataSource 数据源
     * @param pageable   分页参数
     * @return 表元数据分页结果
     */
    Page<MetadataTable> findByDataSource(DataSource dataSource, Pageable pageable);

    /**
     * 分页查询指定数据源ID的表元数据
     *
     * @param dataSourceId 数据源ID
     * @param pageable     分页参数
     * @return 表元数据分页结果
     */
    @Query("SELECT mt FROM MetadataTable mt WHERE mt.dataSource.id = :dataSourceId")
    Page<MetadataTable> findByDataSourceId(@Param("dataSourceId") Long dataSourceId, Pageable pageable);

    /**
     * 分页查询指定数据源和schema的表元数据
     *
     * @param dataSource  数据源
     * @param tableSchema 表模式
     * @param pageable    分页参数
     * @return 表元数据分页结果
     */
    Page<MetadataTable> findByDataSourceAndTableSchema(DataSource dataSource, String tableSchema, Pageable pageable);

    /**
     * 查找指定时间范围内更新的表元数据
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return 表元数据列表
     */
    List<MetadataTable> findByUpdatedAtBetween(LocalDateTime startTime, LocalDateTime endTime);

    /**
     * 查找指定数据源在时间范围内更新的表元数据
     *
     * @param dataSource 数据源
     * @param startTime  开始时间
     * @param endTime    结束时间
     * @return 表元数据列表
     */
    List<MetadataTable> findByDataSourceAndUpdatedAtBetween(DataSource dataSource, LocalDateTime startTime, LocalDateTime endTime);

    /**
     * 统计指定数据源的表数量
     *
     * @param dataSource 数据源
     * @return 表数量
     */
    long countByDataSource(DataSource dataSource);

    /**
     * 统计指定数据源ID的表数量
     *
     * @param dataSourceId 数据源ID
     * @return 表数量
     */
    @Query("SELECT COUNT(mt) FROM MetadataTable mt WHERE mt.dataSource.id = :dataSourceId")
    long countByDataSourceId(@Param("dataSourceId") Long dataSourceId);

    /**
     * 统计指定数据源和schema的表数量
     *
     * @param dataSource  数据源
     * @param tableSchema 表模式
     * @return 表数量
     */
    long countByDataSourceAndTableSchema(DataSource dataSource, String tableSchema);

    /**
     * 检查表是否存在
     *
     * @param dataSource  数据源
     * @param tableSchema 表模式
     * @param tableName   表名
     * @return 是否存在
     */
    boolean existsByDataSourceAndTableSchemaAndTableName(DataSource dataSource, String tableSchema, String tableName);

    /**
     * 删除指定数据源的所有表元数据
     *
     * @param dataSource 数据源
     */
    void deleteByDataSource(DataSource dataSource);

    /**
     * 删除指定数据源ID的所有表元数据
     *
     * @param dataSourceId 数据源ID
     */
    @Modifying
    @Transactional
    @Query("DELETE FROM MetadataTable mt WHERE mt.dataSource.id = :dataSourceId")
    void deleteByDataSourceId(@Param("dataSourceId") Long dataSourceId);

    /**
     * 删除指定数据源和schema的所有表元数据
     *
     * @param dataSource  数据源
     * @param tableSchema 表模式
     */
    void deleteByDataSourceAndTableSchema(DataSource dataSource, String tableSchema);

    /**
     * 批量保存表元数据
     * 重写saveAll方法以优化批量插入性能
     *
     * @param tables 表元数据列表
     * @return 保存后的表元数据列表
     */
    @Override
    <S extends MetadataTable> List<S> saveAll(Iterable<S> tables);

    // ==================== US4: 元数据搜索功能 (T100) ====================

    /**
     * 根据表名搜索表元数据 (模糊匹配)
     * 使用LIKE进行简单模糊搜索
     *
     * @param keyword  搜索关键词
     * @param pageable 分页参数
     * @return 表元数据分页结果
     */
    @Query("SELECT mt FROM MetadataTable mt WHERE LOWER(mt.tableName) LIKE LOWER(CONCAT('%', :keyword, '%'))")
    Page<MetadataTable> searchByTableName(@Param("keyword") String keyword, Pageable pageable);

    /**
     * 根据表注释搜索表元数据 (模糊匹配,支持中文)
     * 使用LIKE进行简单模糊搜索
     *
     * @param keyword  搜索关键词
     * @param pageable 分页参数
     * @return 表元数据分页结果
     */
    @Query("SELECT mt FROM MetadataTable mt WHERE mt.tableComment LIKE CONCAT('%', :keyword, '%')")
    Page<MetadataTable> searchByTableComment(@Param("keyword") String keyword, Pageable pageable);

    /**
     * 全文搜索表元数据 (ParadeDB BM25算法)
     * 使用ParadeDB的pg_search扩展进行全文搜索
     * 注意: 生产环境需要ParadeDB,测试环境降级为LIKE搜索
     *
     * @param keyword  搜索关键词
     * @param pageable 分页参数
     * @return 表元数据分页结果,按BM25相关性评分降序排列
     */
    @Query(value = "SELECT mt.* FROM metadata_table mt " +
            "WHERE LOWER(mt.table_name) LIKE LOWER(CONCAT('%', :keyword, '%')) " +
            "OR mt.table_comment LIKE CONCAT('%', :keyword, '%') " +
            "ORDER BY " +
            "CASE " +
            "  WHEN LOWER(mt.table_name) = LOWER(:keyword) THEN 1 " +
            "  WHEN LOWER(mt.table_name) LIKE LOWER(CONCAT(:keyword, '%')) THEN 2 " +
            "  WHEN mt.table_comment LIKE CONCAT(:keyword, '%') THEN 3 " +
            "  ELSE 4 " +
            "END",
            countQuery = "SELECT COUNT(*) FROM metadata_table mt " +
                    "WHERE LOWER(mt.table_name) LIKE LOWER(CONCAT('%', :keyword, '%')) " +
                    "OR mt.table_comment LIKE CONCAT('%', :keyword, '%')",
            nativeQuery = true)
    Page<MetadataTable> searchByFullText(@Param("keyword") String keyword, Pageable pageable);

    /**
     * 根据表名精确查找表元数据
     * 用于组合搜索场景
     *
     * @param tableName 表名
     * @return 表元数据Optional
     */
    @Query("SELECT mt FROM MetadataTable mt WHERE mt.tableName = :tableName")
    Optional<MetadataTable> findByTableName(@Param("tableName") String tableName);
}
